#target illustrator
(function () {
    if (app.documents.length === 0) { alert("请先打开文档"); return; }
    var sel = app.activeDocument.selection;
    if (!sel || sel.length === 0) { alert("请先选择文字对象（TextFrame/路径文字/区域文字，或包含它们的组）"); return; }

    // ==== ScriptUI 面板 ====
    var dlg = new Window("dialog", "数字排序映射（起始 / 增量）");
    dlg.orientation = "column";
    dlg.alignChildren = ["fill", "top"];
    dlg.margins = 12;

    var info = dlg.add("statictext", undefined,
        "说明：按数值从小到大建立名次；支持负数与小数；相同数值映射为相同结果。",
        { multiline: true }
    );
    info.preferredSize.width = 380;
    info.preferredSize.height = 36;

    var pnl = dlg.add("panel", undefined, "参数");
    pnl.orientation = "column";
    pnl.alignChildren = ["left", "top"];
    pnl.margins = 12;

    var rowStart = pnl.add("group");
    rowStart.add("statictext", undefined, "起始值（数值）：");
    var etStart = rowStart.add("edittext", undefined, "1");
    etStart.characters = 12;

    var rowStep = pnl.add("group");
    rowStep.add("statictext", undefined, "增  量（数值，≠0）：");
    var etStep = rowStep.add("edittext", undefined, "1");
    etStep.characters = 12;

    var btnRow = dlg.add("group");
    btnRow.alignment = "right";
    var okBtn = btnRow.add("button", undefined, "确定", { name: "ok" });
    var cancelBtn = btnRow.add("button", undefined, "取消", { name: "cancel" });

    // ====== 解析数值（支持 ± 和小数点；前后空白允许）======
    function parseNumberStrict(s) {
        if (s == null) return NaN;
        s = String(s).replace(/^\s+|\s+$/g, "");
        // 允许：-12, +3.5, .75, -.5, 0.0
        if (!/^[+-]?(?:\d+\.?\d*|\.\d+)$/.test(s)) return NaN;
        var n = parseFloat(s);
        // 归一化 -0 为 0，避免 -0 与 0 分组不同
        return (n === 0 ? 0 : n);
    }

    var result = dlg.show();
    if (result !== 1) return; // 用户取消

    var startVal = parseNumberStrict(etStart.text);
    if (isNaN(startVal)) { alert("起始值格式不正确：请输入数值（可含±与小数）。"); return; }

    var stepVal = parseNumberStrict(etStep.text);
    if (isNaN(stepVal)) { alert("增量格式不正确：请输入数值（可含±与小数）。"); return; }
    if (stepVal === 0) { alert("增量必须非 0。"); return; }

    // ==== 仅遍历选区，收集 TextFrame ====
    function collectTextFramesFromSelection(selection) {
        var out = [], stack = [];
        for (var i = 0; i < selection.length; i++) stack.push(selection[i]);

        while (stack.length) {
            var it = stack.pop();
            if (!it || !it.typename) continue;

            if (it.typename === "TextFrame") { out.push(it); continue; }
            if (it.typename === "TextRange" && it.parent && it.parent.typename === "TextFrame") {
                out.push(it.parent); continue;
            }
            // 只向下钻被选中的容器，避免全局遍历
            if (it.typename === "GroupItem" || it.typename === "Layer") {
                var kids = it.pageItems;
                for (var k = 0; k < kids.length; k++) stack.push(kids[k]);
                continue;
            }
        }
        // 去重（TextRange 与其父 TextFrame 可能重复）
        var uniq = [], seen = {};
        for (var j = 0; j < out.length; j++) {
            var id = out[j].uuid || out[j].id;
            if (!seen[id]) { seen[id] = true; uniq.push(out[j]); }
        }
        return uniq;
    }

    var tfs = collectTextFramesFromSelection(sel);
    if (tfs.length === 0) { alert("选区中未找到可处理的文字对象（TextFrame）"); return; }

    // ==== 选中文本的“数值”检测（支持负数/小数） ====
    var VALUE_RE = /^\s*[+-]?(?:\d+\.?\d*|\.\d+)\s*$/;

    var entries = [], skipCount = 0;
    for (var i = 0; i < tfs.length; i++) {
        var tf = tfs[i];
        if (tf.locked || tf.hidden) continue;

        var s = String(tf.contents);
        if (VALUE_RE.test(s)) {
            var n = parseNumberStrict(s);
            entries.push({ tf: tf, num: n });
        } else {
            skipCount++;
        }
    }
    if (entries.length === 0) {
        alert("选区内没有符合“数值（含负数/小数）”的文字内容。");
        return;
    }

    // ==== 建立名次（按数值升序；相同数值同名次） ====
    var uSeen = {}, uniques = [];
    for (var e = 0; e < entries.length; e++) {
        var v = entries[e].num; // 已统一 -0 为 0
        if (!uSeen.hasOwnProperty(v)) { uSeen[v] = true; uniques.push(v); }
    }
    uniques.sort(function (a, b) { return a - b; });

    var rankMap = {};
    for (var r = 0; r < uniques.length; r++) rankMap[uniques[r]] = r + 1;

    // ==== 应用映射：输出 = 起始值 + (rank-1) × 增量 ====
    var changed = 0;
    for (var t = 0; t < entries.length; t++) {
        var rank = rankMap[entries[t].num];
        var outVal = String(startVal + (rank - 1) * stepVal);
        if (entries[t].tf.contents !== outVal) {
            entries[t].tf.contents = outVal;
            changed++;
        }
    }

    alert(
        "完成：\n" +
        "  已处理：" + entries.length + "\n" +
        "  修改：" + changed + "\n" +
        "  跳过（非数值）：" + skipCount + "\n" +
        "  不同原始数值个数：" + uniques.length + "\n" +
        "  公式：输出 = 起始值 + (名次-1) × 增量\n" +
        "  已支持：负数与小数（如 -12.5、+.75、.5）"
    );
})();
